package com.xiaozhou.controller;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xiaozhou.function.FunctionManager;
import com.zhipu.oapi.ClientV4;
import com.zhipu.oapi.Constants;
import com.zhipu.oapi.service.v4.model.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author shhzhou
 * @description:
 * @date 2024/10/30 16:49
 */
@RestController
@RequestMapping("/language")
public class LanguageController {

    @Autowired
    private ClientV4 clientV4;

    @Autowired
    private FunctionManager functionManager;


    @GetMapping("/modelOne")
    public ModelApiResponse modelOne(String message) {
        //构造消息列表
        List<ChatMessage> chatMessages = new ArrayList<>();
        // 设置默认系统文本（简单理解是构建模型的人设）
        chatMessages.add(new ChatMessage("system", "你的身份是一个专业的市场营销专家，你的名字叫小林，请以恭敬的语气回答客户的问题！"));
        chatMessages.add(new ChatMessage("user", "你好,你是谁？"));
        chatMessages.add(new ChatMessage("tool", "广州越秀区房价为40000一平方"));
        chatMessages.add(new ChatMessage("tool", "广州越秀区今天天气晴朗，人体温度为28摄氏度，适合去看房"));
        chatMessages.add(new ChatMessage("tool", "广州越秀区看房方便，可以乘坐地下交通，广州地铁1号线"));
        chatMessages.add(new ChatMessage("user", message));

        // 构造模型对象
        ChatCompletionRequest request = new ChatCompletionRequest();
        request.setModel("glm-4-flash");
        request.setMessages(chatMessages);
        request.setStream(false);
        request.setInvokeMethod(Constants.invokeMethod);

        ModelApiResponse modelApiResponse = clientV4.invokeModelApi(request);
        return modelApiResponse;
    }


    /**
     * @Author xiaozhou
     * @Description 流式调用输出 范例    （更优解范例请参考AgentController类中streamModel方法）
     * @Date 11:19 2024/11/1
     * @Param
     * @return
     * @return reactor.core.publisher.Mono<reactor.core.publisher.Flux<com.zhipu.oapi.service.v4.model.ModelData>>
     */
    @RequestMapping("/streamModel")
    public Mono<Flux<ModelData>> streamModel() {

        //构造消息列表
        List<ChatMessage> chatMessages = new ArrayList<>();
        // 设置默认系统文本（简单理解是构建模型的人设）
        chatMessages.add(new ChatMessage("system", "你的身份是一个专业的市场营销专家，你的名字叫小林，请以恭敬的语气回答客户的问题！"));
        chatMessages.add(new ChatMessage("user", "你好,你是谁？"));


        // 构造模型对象
        ChatCompletionRequest request = new ChatCompletionRequest();
        request.setModel("glm-4-flash");
        request.setMessages(chatMessages);
        request.setStream(true);
        request.setInvokeMethod(Constants.invokeMethod);

        ModelApiResponse modelApiResponse = clientV4.invokeModelApi(request);

        Flux<ModelData> flowable = Flux.from(modelApiResponse.getFlowable());

        return Mono.just(flowable);

    }


    /**
     * @return
     * @return com.zhipu.oapi.service.v4.model.ModelApiResponse
     * @Author xiaozhou
     * @Description 大模型实现function call (正常运行)
     * 使用场景：实现外部函数 function call 可以将现在业务系统的数据接入到大模型中，让大模型根据数据进行决策性分析，从而返回决策结果
     * @Date 10:35 2024/10/31
     * @Param message
     */
    @GetMapping("/modelTwo")
    public ModelApiResponse modelTwo(String message) {
        //构造消息列表
        List<ChatMessage> chatMessages = new ArrayList<>();
        // 设置默认系统文本（简单理解是构建模型的人设）
        chatMessages.add(new ChatMessage("system", "你的身份是一个专业的管家，你的名字叫小林，请以恭敬的语气回答客户的问题！"));
        chatMessages.add(new ChatMessage("user", message));

        // 构造工具参数
        List<ChatTool> toolList = new ArrayList<>();
        // 获取地区房价函数
        ChatTool chatTool = new ChatTool();
        chatTool.setType(ChatToolType.FUNCTION.value());

        ChatFunction chatFunction = new ChatFunction();
        chatFunction.setName("getHousePrice");
        chatFunction.setDescription("获取广州越秀区房价");

        ChatFunctionParameters chatFunctionParameters = new ChatFunctionParameters();
        chatFunctionParameters.setType("object");

        Map<String, Object> properties = new HashMap<>();
        properties.put("district", new HashMap<String, Object>() {{
            put("type", "string");
            put("description", "地区：如，越秀区");
        }});
        chatFunctionParameters.setProperties(properties);
        chatFunction.setParameters(chatFunctionParameters);
        chatTool.setFunction(chatFunction);

        // 获取地区天气函数
        ChatTool chatTool2 = new ChatTool();
        chatTool2.setType(ChatToolType.FUNCTION.value());
        ChatFunction chatFunction2 = new ChatFunction();
        chatFunction2.setName("getWeather");
        chatFunction2.setDescription("获取地区天气");
        ChatFunctionParameters chatFunctionParameters2 = new ChatFunctionParameters();
        chatFunctionParameters2.setType("object");
        Map<String, Object> properties2 = new HashMap<>();
        properties2.put("district", new HashMap<String, Object>() {{
            put("type", "string");
            put("description", "地区：如，越秀区");
        }});
        chatFunctionParameters2.setProperties(properties2);
        chatFunction2.setParameters(chatFunctionParameters2);
        chatTool2.setFunction(chatFunction2);

        toolList.add(chatTool);
        toolList.add(chatTool2);

        // 构造模型对象
        ChatCompletionRequest request = new ChatCompletionRequest();
        request.setModel("glm-4-flash");
        request.setMessages(chatMessages);
        request.setStream(false);
        request.setTools(toolList);
        request.setToolChoice("auto");
        request.setInvokeMethod(Constants.invokeMethod);

        ModelApiResponse modelApiResponse = clientV4.invokeModelApi(request);

        ChatFunctionCall function = modelApiResponse.getData().getChoices().get(0).getMessage().getTool_calls().get(0).getFunction();
        String functionName = function.getName();
        String arguments;
        try {
            arguments = new ObjectMapper().readTree(function.getArguments().textValue()).findValue("district").asText();
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }

        // 调用函数
        String result = functionManager.callFunction(functionName, arguments);

        chatMessages.add(new ChatMessage("tool", result));
        ChatCompletionRequest request1 = ChatCompletionRequest.builder()
                .model("glm-4-flash")
                .messages(chatMessages)
                .stream(false)
                .invokeMethod(Constants.invokeMethod)
                .build();
        return clientV4.invokeModelApi(request1);
    }


}
